﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Songhay.Mvvm.Models
{
    /// <summary>
    /// Stores and verifies all of the conventional and known Bookmark locations
    /// in a “rich” Client with Page Navigation.
    /// </summary>
    public class NavigationBookmarkData
    {
        static NavigationBookmarkData()
        {
            keyForGetDataFormat = "GetDataFormat";
            keyForNewDataFormat = "NewDataFormat";

            keyForDeleteConfirmation = "DeleteConfirmation";
            keyForEntityAssociationSelection = "EntityAssociationSelection";
            keyForEntityAssociations = "EntityAssociations";
            keyForErrorMessage = "ErrorMessage";
            keyForIndex = "Index";
            keyForInformationMessage = "InformationMessage";
            keyForSearch = "Search";
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="NavigationBookmarkData" /> class.
        /// </summary>
        public NavigationBookmarkData()
        {
            this._navigationBookmarks = new Dictionary<string,string>();

            this._navigationBookmarks.Add(keyForGetDataFormat, "#/{0}/{1}");
            this._navigationBookmarks.Add(keyForNewDataFormat, "#/{0}/New");

            this._navigationBookmarks.Add(keyForIndex, "#/");

            this.AddBookmark(keyForDeleteConfirmation);
            this.AddBookmark(keyForErrorMessage);
            this.AddBookmark(keyForInformationMessage);

            this.AddBookmark(keyForEntityAssociationSelection);
            this.AddBookmark(keyForEntityAssociations);
            this.AddBookmark(keyForSearch);
        }

        /// <summary>
        /// Adds the bookmark.
        /// </summary>
        /// <param name="key">The key.</param>
        public void AddBookmark(string key)
        {
            this.AddBookmark(key, key);
        }

        /// <summary>
        /// Adds the bookmark.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="bookmarkPart">The bookmark part.</param>
        public void AddBookmark(string key, string bookmarkPart)
        {
            if(string.IsNullOrEmpty(key))
                throw new ArgumentNullException("key", "The expected key is not here.");
            if(string.IsNullOrEmpty(bookmarkPart))
                throw new ArgumentNullException("bookmarkPart", "The expected bookmark part is not here.");

            this._navigationBookmarks.Add(key, string.Format("#/{0}", bookmarkPart));
        }

        #region conventional getters:

        /// <summary>
        /// Gets the pattern for get data format.
        /// </summary>
        public string GetPatternForGetDataFormat()
        {
            return this._navigationBookmarks[keyForGetDataFormat];
        }

        /// <summary>
        /// Gets the pattern for new data format.
        /// </summary>
        public string GetPatternForNewDataFormat()
        {
            return this._navigationBookmarks[keyForNewDataFormat];
        }

        /// <summary>
        /// Gets the delete confirmation bookmark.
        /// </summary>
        public string GetBookmarkForDeleteConfirmation()
        {
            return this._navigationBookmarks[keyForDeleteConfirmation];
        }

        /// <summary>
        /// Gets the bookmark for entity association selection.
        /// </summary>
        public string GetBookmarkForEntityAssociationSelection()
        {
            return this._navigationBookmarks[keyForEntityAssociationSelection];
        }

        /// <summary>
        /// Gets the associations bookmark.
        /// </summary>
        public string GetBookmarkForEntityAssociations()
        {
            return this._navigationBookmarks[keyForEntityAssociations];
        }

        /// <summary>
        /// Gets the error message bookmark.
        /// </summary>
        public string GetBookmarkForErrorMessage()
        {
            return this._navigationBookmarks[keyForErrorMessage];
        }

        /// <summary>
        /// Gets the index bookmark.
        /// </summary>
        public string GetBookmarkForIndex()
        {
            return this._navigationBookmarks[keyForIndex];
        }

        /// <summary>
        /// Gets the information message bookmark.
        /// </summary>
        public string GetBookmarkForInformationMessage()
        {
            return this._navigationBookmarks[keyForInformationMessage];
        }

        /// <summary>
        /// Gets the search bookmark.
        /// </summary>
        public string GetBookmarkForSearch()
        {
            return this._navigationBookmarks[keyForSearch];
        }

        /// <summary>
        /// Gets the bookmark with key.
        /// </summary>
        /// <param name="key">The key.</param>
        public string GetBookmarkWithKey(string key)
        {
            if(this._navigationBookmarks == null) return null;
            return this._navigationBookmarks[key];
        }

        #endregion

        #region bookmark tests:

        /// <summary>
        /// Determines whether the specified key represents a bookmark.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns>
        ///   <c>true</c> if key represents a bookmark; otherwise, <c>false</c>.
        /// </returns>
        public bool HasBookmarkKey(string key)
        {
            if(this._navigationBookmarks == null) return false;
            return this._navigationBookmarks.Keys.Contains(key);
        }

        /// <summary>
        /// Determines whether bookmark is unknown.
        /// </summary>
        /// <returns>
        ///   <c>true</c> if bookmark is unknown; otherwise, <c>false</c>.
        /// </returns>
        public bool IsBookmarkUnknown()
        {
            if(string.IsNullOrEmpty(this._currentBookmark)) return false;
            var location = this._currentBookmark;

            var test = true;

            var testParticle = (!string.IsNullOrEmpty(location) && location.StartsWith("/")) ?
                string.Concat("#", location) : location;

            var key = this._navigationBookmarks.Values
                .Where(i => i == testParticle)
                .FirstOrDefault();

            test = (key == null);

            return test;
        }

        /// <summary>
        /// Determines whether bookmark is delete confirmation message.
        /// </summary>
        /// <returns>
        ///   <c>true</c> if bookmark is delete confirmation message; otherwise, <c>false</c>.
        /// </returns>
        public bool IsBookmarkDeleteConfirmation()
        {
            return this.IsBookMark("/DeleteConfirmation");
        }

        /// <summary>
        /// Determines whether bookmark is error message.
        /// </summary>
        /// <returns>
        ///   <c>true</c> if bookmark is error message; otherwise, <c>false</c>.
        /// </returns>
        public bool IsBookmarkErrorMessage()
        {
            return this.IsBookMark("/ErrorMessage");
        }


        /// <summary>
        /// Determines whether bookmark is index location.
        /// </summary>
        /// <returns>
        ///   <c>true</c> if bookmark is index location; otherwise, <c>false</c>.
        /// </returns>
        public bool IsBookmarkIndex()
        {
            return this.IsBookMark("/");
        }

        /// <summary>
        /// Determines whether bookmark is information message.
        /// </summary>
        /// <returns>
        ///   <c>true</c> if bookmark is information message; otherwise, <c>false</c>.
        /// </returns>
        public bool IsBookmarkInformationMessage()
        {
            return this.IsBookMark("/InformationMessage");
        }


        /// <summary>
        /// Determines whether bookmark is insert format.
        /// </summary>
        /// <returns>
        ///   <c>true</c> if bookmark is insert format; otherwise, <c>false</c>.
        /// </returns>
        public bool IsBookmarkInsertFormat()
        {
            return this.IsBookMark("New");
        }

        public bool IsBookmarkSearch()
        {
            return false;
        }

        bool IsBookMark(string testParticle)
        {
            if(string.IsNullOrEmpty(this._currentBookmark)) return false;
            var location = this._currentBookmark;
            return (!string.IsNullOrEmpty(location) && location.EndsWith(testParticle));
        }

        #endregion

        /// <summary>
        /// Sets the bookmark context.
        /// </summary>
        /// <param name="currentBookmark">The current bookmark.</param>
        public void SetBookmarkContext(string currentBookmark)
        {
            this._currentBookmark = currentBookmark;
        }

        static readonly string keyForGetDataFormat;
        static readonly string keyForNewDataFormat;

        static readonly string keyForDeleteConfirmation;
        static readonly string keyForEntityAssociationSelection;
        static readonly string keyForEntityAssociations;
        static readonly string keyForErrorMessage;
        static readonly string keyForIndex;
        static readonly string keyForInformationMessage;
        static readonly string keyForSearch;

        string _currentBookmark;

        Dictionary<string, string> _navigationBookmarks;
    }
}
